package com.iss.soc.httpclient;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.net.CookieManager;
import java.net.CookiePolicy;
import java.util.concurrent.TimeUnit;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.iss.soc.exception.ErrorMsg;
import com.iss.soc.exception.SocServiceException;
import okhttp3.*;
import okhttp3.logging.HttpLoggingInterceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import retrofit2.*;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Created by Administrator on 2016/7/14 0014.
 */
public class RestClient {
    private final Logger logger = LoggerFactory.getLogger(RestClient.class);
    private OkHttpClient httpClient;
    //拦截器来处理基本URL。
    private Retrofit retrofit;


    protected RestClient(OkHttpClient httpClient,
                         Retrofit retrofit
    ) {
        this.httpClient = httpClient;
        this.retrofit = retrofit;
    }

    //http客户端
    public OkHttpClient httpClient() {
        return httpClient;
    }

    //改造实例
    public Retrofit retrofit() {
        return retrofit;
    }

    public   ResponseBody getPostOrDeleteResult(retrofit2.Response<ResponseBody> response) throws SocServiceException, InterruptedException{
        if (response == null) {
            logger.error("系统出现异常,响应");
            throw new SocServiceException("");
        }
        int statusCode = response.code();
        ResponseBody responseBody;
        if (response.isSuccessful()) {
            responseBody = response.body();
        } else {
            responseBody = response.errorBody();
        }
        if (statusCode != 200 && statusCode != 202 && statusCode != 204) {
            SocServiceException exception = new SocServiceException(statusCode + " 不是正常请求的状态码");
            exception.setResponse(response);
            ErrorMsg error=null;
            String errorbody="";
            if (responseBody != null) {
                try {
                   errorbody= responseBody.string();
                }catch (IOException e){
                    logger.error("系统出现异常,网络异常");
                    throw exception;
                }
                if(errorbody.indexOf("<")!=-1){
                    logger.error("系统出现异常");
                    throw exception;
                }else {
                    Gson gson=new Gson();
                    error = gson.fromJson(errorbody, new TypeToken<ErrorMsg>() {
                    }.getType());
                    error.setStatus(statusCode+"");
                    exception.setBody(error);
                }
                responseBody.close();
            }
            throw exception;
        }
        return  responseBody;
    }
    /*
     *构建器类来构建一个REST客户端
     */
    public static class Builder {
        /**
         * 动态基本URL变量用“{”和“}”。
         */
        protected String baseUrl;
        /**
         * builder构建一个{ @link OkHttpClient }。
         */
        protected OkHttpClient.Builder httpClientBuilder;
        /**
         * 建造者建造一个{ @link改造}
         */
        protected Retrofit.Builder retrofitBuilder;
        /**
         * 内部构建实例
         * .
         */
        protected Buildable buildable;
        /**
         * 创建构建器的一个实例的基于URL的服务
         */
        public Builder() {
            this(new OkHttpClient.Builder(), new Retrofit.Builder());
        }


        /**
         * 创建构建器的一个实例的URL和2进制生成器
         *
         * @param httpClientBuilder the builder to build an {@link OkHttpClient}
         * @param retrofitBuilder   the builder to build a {@link Retrofit}.
         */
        public Builder(OkHttpClient.Builder httpClientBuilder, Retrofit.Builder retrofitBuilder) {
            if (httpClientBuilder == null) {
                throw new IllegalArgumentException("httpClientBuilder == null");
            }
            if (retrofitBuilder == null) {
                throw new IllegalArgumentException("retrofitBuilder == null");
            }
            CookieManager cookieManager = new CookieManager();
            cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
            this.httpClientBuilder = httpClientBuilder;
            this.retrofitBuilder = retrofitBuilder;
            this.buildable = new Buildable();
        }

        /**
         * 设置动态基本URL。
         *
         * @param baseUrl the base URL to use. 要使用的URL。
         * @return the builder itself for chaining.  生成器本身的连接
         */
        public Buildable withBaseUrl(String baseUrl) {
            this.baseUrl = baseUrl;
            return buildable;
        }

        /**
         * 设置默认的基URL从服务端。
         *
         * @param serviceClientClass the service client class containing a default base URL.
         * @return the builder itself for chaining.
         */
        public Buildable withDefaultBaseUrl(Class<?> serviceClientClass) {
            try {
                Field field = serviceClientClass.getDeclaredField("DEFAULT_BASE_URL");
                field.setAccessible(true);
                baseUrl = (String) field.get(null);
            } catch (NoSuchFieldException | IllegalAccessException e) {
                throw new UnsupportedOperationException("Cannot read static field DEFAULT_BASE_URL", e);
            }
            return buildable;
        }


        /**
         * 设置默认的基URL从Azure环境。
         *
         * @return the builder itself for chaining
         */
        public RestClient.Builder.Buildable withDefaultBaseUrl(String url) {
            withBaseUrl(url);
            return buildable;
        }


        public class Buildable {
            /**
             * 设置日志级别。
             *
             * @param logLevel the {@link okhttp3.logging.HttpLoggingInterceptor.Level} enum.
             * @return the builder itself for chaining.
             */
            public Buildable withLogLevel(HttpLoggingInterceptor.Level logLevel) {
                httpClientBuilder.addInterceptor(new HttpLoggingInterceptor().setLevel(logLevel));
                return this;
            }

            /**
             * HTTP客户机上设置读取超时。默认是10秒。
             *
             * @param timeout the timeout numeric value
             * @param unit    the time unit for the numeric value
             * @return the builder itself for chaining
             */
            public Buildable withReadTimeout(long timeout, TimeUnit unit) {
                httpClientBuilder.readTimeout(timeout, unit);
                return this;
            }

            /**
             * HTTP客户机上设置连接超时。默认是10秒。
             *
             * @param timeout the timeout numeric value
             * @param unit    the time unit for the numeric value
             * @return the builder itself for chaining
             */
            public Buildable withConnectionTimeout(long timeout, TimeUnit unit) {
                httpClientBuilder.connectTimeout(timeout, unit);
                return this;
            }

            /**
             * @param maxIdleConnections the maximum idle connections
             * @return the builder itself for chaining
             */
            public Buildable withMaxIdleConnections(int maxIdleConnections) {
                httpClientBuilder.connectionPool(new ConnectionPool(maxIdleConnections, 5, TimeUnit.MINUTES));
                return this;
            }


            /**
             * 添加一个拦截器Http客户端管道
             *
             * @param interceptor the interceptor to add.
             * @return the builder itself for chaining.
             */
            public Buildable withInterceptor(Interceptor interceptor) {
                httpClientBuilder.addInterceptor(interceptor);
                return this;
            }

            /**
             * 建立一个RestClient当前配置。
             *
             * @return a {@link RestClient}.
             */
            public RestClient build() {
                ObjectMapper mapper = new ObjectMapper();
                OkHttpClient httpClient = httpClientBuilder
                        .build();
                return new RestClient(httpClient,
                        retrofitBuilder
                                .baseUrl(baseUrl)
                                .addConverterFactory(GsonConverterFactory.create())
                                .client(httpClient)
                                .build()
                );
            }

        }
    }
}

